home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / Rect.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  21.7 KB  |  741 lines  |  [TEXT/CWIE]

  1. // Rect.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import netscape.util.*;
  8.  
  9. /** Object subclass representing a rectangle (its origin and positive size).
  10.   */
  11.  
  12. public class Rect implements Codable {
  13.     /** The Rect's X-coordinate. */
  14.     public int          x;
  15.     /** The Rect's Y-coordinate. */
  16.     public int          y;
  17.     /** The Rect's width. */
  18.     public int          width;
  19.     /** The Rect's height. */
  20.     public int          height;
  21.  
  22.     static private Vector       _rectCache = new Vector();
  23.     static private boolean      _cacheRects = true;
  24.  
  25.     static final String         X_KEY = "x";
  26.     static final String         Y_KEY = "y";
  27.     static final String         WIDTH_KEY = "width";
  28.     static final String         HEIGHT_KEY = "height";
  29.  
  30.  
  31.  
  32. /* static methods */
  33.  
  34.     /** Returns <b>true</b> if the rect defined by
  35.       * (<b>x</b>, <b>y</b>, <b>width</b>, <b>height</b>) contains the
  36.       * point (<b>pointX</b>, <b>pointY</b>).
  37.       */
  38.     public static boolean contains(int x, int y, int width, int height,
  39.                                         int pointX, int pointY) {
  40.         return (pointX >= x && pointX < x + width &&
  41.                 pointY >= y && pointY < y + height);
  42.     }
  43.  
  44.     /** Returns a Rect representing the intersection of <b>rect1</b> and
  45.       * <b>rect2</b>.
  46.       */
  47.     public static Rect rectFromIntersection(Rect rect1, Rect rect2) {
  48.         Rect    newRect;
  49.  
  50.         newRect = new Rect(rect1);
  51.         newRect.intersectWith(rect2);
  52.  
  53.         return newRect;
  54.     }
  55.  
  56.     /** Returns a Rect representing the union of <b>rect1</b> and
  57.       * <b>rect2</b>.
  58.       */
  59.     public static Rect rectFromUnion(Rect rect1, Rect rect2) {
  60.         Rect    newRect;
  61.  
  62.         newRect = new Rect(rect1);
  63.         newRect.unionWith(rect2);
  64.  
  65.         return newRect;
  66.     }
  67.  
  68.  
  69. /* constructors */
  70.  
  71.  
  72.     /** Constructs a Rect with origin (0, 0) and zero width and height.
  73.      */
  74.     public Rect() {
  75.     }
  76.  
  77.     /** Constructs a Rect with origin
  78.       * (<b>x</b>, <b>y</b>) and size (<b>width</b>, <b>height</b>).
  79.       */
  80.     public Rect(int x, int y, int width, int height) {
  81.         this.x = x;
  82.         this.y = y;
  83.         this.width = width;
  84.         this.height = height;
  85.     }
  86.  
  87.     /** Constructs a Rect with the same origin and size as <b>templateRect</b>.
  88.       */
  89.     public Rect(Rect templateRect) {
  90.         x = templateRect.x;
  91.         y = templateRect.y;
  92.         width = templateRect.width;
  93.         height = templateRect.height;
  94.     }
  95.  
  96.     /** Returns the Rect's String representation.
  97.       */
  98.     public String toString() {
  99.         return "(" + x + ", " + y + ", " + width + ", " + height + ")";
  100.     }
  101.  
  102. /* attributes */
  103.  
  104.  
  105.     /** Sets the Rect's origin to (<b>x</b>, <b>y</b>) and size to
  106.       * (<b>width</b>, <b>height</b>).  If <b>width</b> or <b>height</b> are
  107.       * negative, sets them to zero.
  108.       */
  109.     public void setBounds(int x, int y, int width, int height) {
  110.         this.x = x;
  111.         this.y = y;
  112.         this.width = width < 0 ? 0 : width;
  113.         this.height = height < 0 ? 0 : height;
  114.     }
  115.  
  116.     /** Sets the Rect to have the same origin and size as <b>rect</b>.  If
  117.       * <b>rect</b> is <b>null</b>, sets the Rect's origin to (0, 0) and zero
  118.       * width and height.
  119.       * @see #setBounds(int, int, int, int)
  120.       */
  121.     public void setBounds(Rect rect) {
  122.         if (rect == null) {
  123.             setBounds(0, 0, 0, 0);
  124.         } else {
  125.             setBounds(rect.x, rect.y, rect.width, rect.height);
  126.         }
  127.     }
  128.  
  129.     /** Sets the Rect's origin to (<b>x1</b>, <b>y1</b>) and size to
  130.       * (<b>x2 - x1</b>, <b>y2 - y1</b>).
  131.       */
  132.     public void setCoordinates(int x1, int y1, int x2, int y2) {
  133.         setBounds(x1, y1, x2 - x1, y2 - y1);
  134.     }
  135.  
  136.     /** Sets the Rect's origin to (<b>x</b>, <b>y</b>).
  137.       */
  138.     public void moveTo(int x, int y) {
  139.         this.x = x;
  140.         this.y = y;
  141.     }
  142.  
  143.     /** Moves the Rect's origin by (<b>deltaX</b>, <b>deltaY</b>).
  144.       */
  145.     public void moveBy(int deltaX, int deltaY) {
  146.         x += deltaX;
  147.         y += deltaY;
  148.     }
  149.  
  150.     /** Sets the Rect's size to (<b>width</b>, <b>height</b>).
  151.       */
  152.     public void sizeTo(int width, int height) {
  153.         this.width = width < 0 ? 0 : width;
  154.         this.height = height < 0 ? 0 : height;
  155.     }
  156.  
  157.     /** Changes the Rect's size by (<b>deltaWidth</b>, <b>deltaHeight</b>).
  158.       */
  159.     public void sizeBy(int deltaWidth, int deltaHeight) {
  160.         width += deltaWidth;
  161.         if (width < 0) {
  162.             width = 0;
  163.         }
  164.         height += deltaHeight;
  165.         if (height < 0) {
  166.             height = 0;
  167.         }
  168.     }
  169.  
  170.     /** Moves the Rect's left and right sides by <b>deltaX</b> pixels and its
  171.       * top and bottom sides by <b>deltaY</b>.  For example, starting with a
  172.       * Rect with dimensions (5, 5, 10, 10), <b>growBy(1, -1)</b> leaves the
  173.       * Rect with the dimensions (4, 6, 12, 8).
  174.       */
  175.     public void growBy(int deltaX, int deltaY) {
  176.         x -= deltaX;
  177.         y -= deltaY;
  178.         width += 2 * deltaX;
  179.         height += 2 * deltaY;
  180.  
  181.         if (width < 0) {
  182.             width = 0;
  183.         }
  184.         if (height < 0) {
  185.             height = 0;
  186.         }
  187.     }
  188.  
  189.  
  190.  
  191. /* rect coordinate convenience methods */
  192.  
  193.  
  194.     /** Convenience method for computing x + width.
  195.       */
  196.     public int maxX() {
  197.         return x + width;
  198.     }
  199.  
  200.     /** Convenience method for computing y + height.
  201.       */
  202.     public int maxY() {
  203.         return y + height;
  204.     }
  205.  
  206.     /** Convenience method for computing x + width / 2.
  207.       */
  208.     public int midX() {
  209.         return x + width / 2;
  210.     }
  211.  
  212.     /** Convenience method for computing y + height / 2.
  213.       */
  214.     public int midY() {
  215.         return y + height / 2;
  216.     }
  217.  
  218.     /** Returns <b>true</b> if the Rect equals <b>anObject</b>.
  219.       */
  220.     public boolean equals(Object anObject) {
  221.         Rect    rect;
  222.  
  223.         if (!(anObject instanceof Rect))
  224.             return false;
  225.  
  226.         rect = (Rect)anObject;
  227.         return (rect.x == x && rect.y == y && rect.width == width &&
  228.                 rect.height == height);
  229.     }
  230.  
  231.     /** Returns the Rect's hash code.
  232.       */
  233.     public int hashCode() {
  234.         // I don't know a good hash function for rects.  ALERT!
  235.         return x ^ y ^ width ^ height;
  236.     }
  237.  
  238.     /** Returns <b>true</b> if the Rect has zero width or height.
  239.       */
  240.     public boolean isEmpty() {
  241.         return (width == 0 || height == 0);
  242.     }
  243.  
  244.     /** Returns <b>true</b> if the Rect contains the point
  245.       * (<b>x</b>, <b>y</b>).
  246.       */
  247.     public boolean contains(int x, int y) {
  248.         return (x >= this.x && x < this.x + width &&
  249.                 y >= this.y && y < this.y + height);
  250.     }
  251.  
  252.     /** Returns <b>true</b> if the Rect contains <b>aPoint</b>.
  253.       * @see #contains(int, int)
  254.       */
  255.     public boolean contains(Point aPoint) {
  256.         return contains(aPoint.x, aPoint.y);
  257.     }
  258.  
  259.     /** Returns <b>true</b> if the Rect completely contains <b>aRect</b>.
  260.       */
  261.     public boolean contains(Rect aRect) {
  262.         if (aRect == null) {
  263.             return false;
  264. //      } else if (aRect.width == 0 || aRect.height == 0 ||
  265. //            width == 0 || height == 0) {
  266. //            return false;
  267.         }
  268.  
  269.         if (aRect.x >= x && (aRect.x + aRect.width <= x + width) &&
  270.             aRect.y >= y && (aRect.y + aRect.height <= y + height)) {
  271.             return true;
  272.         }
  273.  
  274.         return false;
  275.     }
  276.  
  277.     /** Returns <b>true</b> if the Rect and the rectangle (<b>x</b>, <b>y</b>,
  278.       * <b>width</b>, <b>height</b>) overlap.
  279.       */
  280.     public boolean intersects(int x, int y, int width, int height) {
  281.         if (this.x >= x + width || this.x + this.width <= x ||
  282.             this.y >= y + height || this.y + this.height <= y) {
  283.             return false;
  284.         }
  285.  
  286.         return !(this.width == 0 || this.height == 0 || width == 0 ||
  287.                  height == 0);
  288.     }
  289.  
  290.     /** Returns <b>true</b> if the Rect and <b>aRect</b> overlap.
  291.       */
  292.     public boolean intersects(Rect aRect) {
  293.         if (aRect == null) {
  294.             return false;
  295.         }
  296.  
  297.         return intersects(aRect.x, aRect.y, aRect.width, aRect.height);
  298.     }
  299.  
  300.  
  301. /* combining with another rect */
  302.  
  303.     /** Sets the Rect's origin and size to correspond to the intersection of
  304.       * the Rect's current dimensions and the rectangle (<b>x</b>, <b>y</b>,
  305.       * <b>width</b>, <b>height</b>).
  306.       */
  307.     public void intersectWith(int x, int y, int width, int height) {
  308.         int     x1, y1, x2, y2, myx2, myy2;
  309.  
  310.         x1 = x;
  311.         y1 = y;
  312.         x2 = x1 + width;
  313.         y2 = y1 + height;
  314.         myx2 = this.x + this.width;
  315.         myy2 = this.y + this.height;
  316.  
  317.         if (this.x >= x2 || myx2 <= x1) {
  318.             x1 = x2 = 0;
  319.         } else if (this.x > x1 && this.x < x2) {
  320.             x1 = this.x;
  321.  
  322.             if (myx2 < x2) {
  323.                 x2 = myx2;
  324.             }
  325.         } else if (myx2 > x1 && myx2 < x2) {
  326.             x2 = myx2;
  327.         }
  328.  
  329.         if (this.y >= y2 || myy2 <= y1) {
  330.             y1 = y2 = 0;
  331.         } else if (this.y > y1 && this.y < y2) {
  332.             y1 = this.y;
  333.  
  334.             if (myy2 < y2) {
  335.                 y2 = myy2;
  336.             }
  337.         } else if (myy2 > y1 && myy2 < y2) {
  338.             y2 = myy2;
  339.         }
  340.  
  341.         setCoordinates(x1, y1, x2, y2);
  342.     }
  343.  
  344.     /** Sets the Rect's origin and size to correspond to the intersection of
  345.       * the Rect's current dimensions and <b>aRect</b>.
  346.       */
  347.     public void intersectWith(Rect aRect) {
  348.         intersectWith(aRect.x, aRect.y, aRect.width, aRect.height);
  349.     }
  350.  
  351.     /** Returns a new Rect corresponding to the intersection of the Rect and
  352.       * <b>aRect</b>
  353.       */
  354.     public Rect intersectionRect(Rect aRect) {
  355.         int     x1, y1, x2, y2, myx2, myy2;
  356.  
  357.         x1 = aRect.x;
  358.         y1 = aRect.y;
  359.         x2 = aRect.x + aRect.width;
  360.         y2 = aRect.y + aRect.height;
  361.         myx2 = x + width;
  362.         myy2 = y + height;
  363.  
  364.         if (x >= x2 || myx2 <= x1 || y >= y2 || myy2 <= y1) {
  365.             return new Rect();
  366.         }
  367.  
  368.         if (x > x1 && x < x2) {
  369.             x1 = x;
  370.  
  371.             if (myx2 < x2) {
  372.                 x2 = myx2;
  373.             }
  374.         } else if (myx2 > x1 && myx2 < x2) {
  375.             x2 = myx2;
  376.         }
  377.  
  378.         if (y > y1 && y < y2) {
  379.             y1 = y;
  380.  
  381.             if (myy2 < y2) {
  382.                 y2 = myy2;
  383.             }
  384.         } else if (myy2 > y1 && myy2 < y2) {
  385.             y2 = myy2;
  386.         }
  387.  
  388.         return new Rect(x1, y1, x2 - x1, y2 - y1);
  389.     }
  390.  
  391.     /** Sets the Rect's origin and size to correspond to the union of the
  392.       * the Rect and the rectangle (<b>x</b>, <b>y</b>, <b>width</b>,
  393.       * <b>height</b>).
  394.       */
  395.     public void unionWith(int x, int y, int width, int height) {
  396.         int     x1, y1, x2, y2;
  397.  
  398.         x1 = this.x < x ? this.x : x;
  399.         x2 = x + width;
  400.         if (this.x + this.width > x2) {
  401.             x2 = this.x + this.width;
  402.         }
  403.  
  404.         y1 = this.y < y ? this.y : y;
  405.         y2 = y + height;
  406.         if (this.y + this.height > y2) {
  407.             y2 = this.y + this.height;
  408.         }
  409.  
  410.         setCoordinates(x1, y1, x2, y2);
  411.     }
  412.  
  413.     /** Sets the Rect's origin and size to correspond to the union of the
  414.       * the Rect and <b>aRect</b>.
  415.       */
  416.     public void unionWith(Rect aRect) {
  417.         if (aRect == null) {
  418.             return;
  419.         }
  420.  
  421.         unionWith(aRect.x, aRect.y, aRect.width, aRect.height);
  422.     }
  423.  
  424.     /** Returns a new Rect corresponding to the union of the Rect and
  425.       * <b>aRect</b>.
  426.       */
  427.     public Rect unionRect(Rect aRect) {
  428.         int     myx2, myy2, x1, y1, x2, y2;
  429.  
  430.         if (aRect == null) {
  431.             return new Rect(this);
  432.         }
  433.  
  434.         x1 = x < aRect.x ? x : aRect.x;
  435.         x2 = aRect.x + aRect.width;
  436.         myx2 = x + width;
  437.         if (myx2 > x2) {
  438.             x2 = myx2;
  439.         }
  440.  
  441.         y1 = y < aRect.y ? y : aRect.y;
  442.         y2 = aRect.y + aRect.height;
  443.         myy2 = y + height;
  444.         if (myy2 > y2) {
  445.             y2 = myy2;
  446.         }
  447.  
  448.         return new Rect(x1, y1, x2 - x1, y2 - y1);
  449.     }
  450.  
  451.     void filterEmptyRects(Vector aVector) {
  452.         Rect    nextRect;
  453.         int     i;
  454.  
  455.         i = aVector.count();
  456.         while (i-- > 0) {
  457.             nextRect = (Rect)aVector.elementAt(i);
  458.             if (nextRect.width == 0 || nextRect.height == 0) {
  459.                 aVector.removeElementAt(i);
  460.             }
  461.         }
  462.     }
  463.  
  464.     /** Fills <b>rects</b> with Rects representing the regions within the
  465.       * Rect that do not overlap with <b>aRect</b>.  If the two Rects do not
  466.       * overlap, it leaves <b>rects</b> empty.
  467.       */
  468.     public void computeDisunionRects(Rect aRect, Vector rects) {
  469.         if (aRect == null || !intersects(aRect) || rects == null) {
  470.             return;
  471.         }
  472.  
  473.         if (aRect.contains(this)) {
  474.             return;
  475.         }
  476.  
  477.         /* -1 */
  478.         if (contains(aRect)) {
  479.             rects.addElement(Rect.newRect(x, y, aRect.x - x, height));
  480.             rects.addElement(Rect.newRect(aRect.x, y, aRect.width,
  481.                                           aRect.y - y));
  482.             rects.addElement(Rect.newRect(aRect.x, aRect.maxY(), aRect.width,
  483.                                           maxY() - aRect.maxY()));
  484.             rects.addElement(Rect.newRect(aRect.maxX(), y,
  485.                                           maxX() - aRect.maxX(), height));
  486.  
  487.             filterEmptyRects(rects);
  488.             return;
  489.         }
  490.  
  491.         /* 1 */
  492.         if (aRect.x <= x && aRect.y <= y) {
  493.             if (aRect.maxX() > maxX()) {
  494.                 rects.addElement(Rect.newRect(x, aRect.maxY(), width,
  495.                                               maxY() - aRect.maxY()));
  496.             } else if (aRect.maxY() > maxY()) {
  497.                 rects.addElement(Rect.newRect(aRect.maxX(), y,
  498.                                               maxX() - aRect.maxX(), height));
  499.             } else {
  500.                 rects.addElement(Rect.newRect(aRect.maxX(), y,
  501.                                               maxX() - aRect.maxX(),
  502.                                               aRect.maxY() - y));
  503.                 rects.addElement(Rect.newRect(x, aRect.maxY(), width,
  504.                                               maxY() - aRect.maxY()));
  505.             }
  506.  
  507.             filterEmptyRects(rects);
  508.             return;
  509.         }
  510.  
  511.         /* 2 */
  512.         if (aRect.x <= x && aRect.maxY() >= maxY()) {
  513.             if (aRect.maxX() > maxX()) {
  514.                 rects.addElement(Rect.newRect(x, y, width, aRect.y - y));
  515.             } else {
  516.                 rects.addElement(Rect.newRect(x, y, width, aRect.y - y));
  517.                 rects.addElement(Rect.newRect(aRect.maxX(), aRect.y,
  518.                                               maxX() - aRect.maxX(),
  519.                                               maxY() - aRect.y));
  520.             }
  521.  
  522.             filterEmptyRects(rects);
  523.             return;
  524.         }
  525.  
  526.         /* 3 */
  527.         if (aRect.x <= x) {
  528.             if (aRect.maxX() >= maxX()) {
  529.                 rects.addElement(Rect.newRect(x, y, width, aRect.y - y));
  530.                 rects.addElement(Rect.newRect(x, aRect.maxY(), width,
  531.                                               maxY() - aRect.maxY()));
  532.             } else {
  533.                 rects.addElement(Rect.newRect(x, y, width, aRect.y - y));
  534.                 rects.addElement(Rect.newRect(aRect.maxX(), aRect.y,
  535.                                               maxX() - aRect.maxX(),
  536.                                               aRect.height));
  537.                 rects.addElement(Rect.newRect(x, aRect.maxY(), width,
  538.                                               maxY() - aRect.maxY()));
  539.             }
  540.  
  541.             filterEmptyRects(rects);
  542.             return;
  543.         }
  544.  
  545.         /* 4 */
  546.         if (aRect.x <= maxX() && aRect.maxX() > maxX()) {
  547.             if (aRect.y <= y && aRect.maxY() > maxY()) {
  548.                 rects.addElement(Rect.newRect(x, y, aRect.x - x, height));
  549.             } else if (aRect.y <= y) {
  550.                 rects.addElement(Rect.newRect(x, y, aRect.x - x,
  551.                                               aRect.maxY() - y));
  552.                 rects.addElement(Rect.newRect(x, aRect.maxY(), width,
  553.                                               maxY() - aRect.maxY()));
  554.             } else if (aRect.maxY() > maxY()) {
  555.                 rects.addElement(Rect.newRect(x, y, width, aRect.y - y));
  556.                 rects.addElement(Rect.newRect(x, aRect.y, aRect.x - x,
  557.                                               maxY() - aRect.y));
  558.             } else {
  559.                 rects.addElement(Rect.newRect(x, y, width, aRect.y - y));
  560.                 rects.addElement(Rect.newRect(x, aRect.y, aRect.x - x,
  561.                                               aRect.height));
  562.                 rects.addElement(Rect.newRect(x, aRect.maxY(), width,
  563.                                               maxY() - aRect.maxY()));
  564.             }
  565.  
  566.             filterEmptyRects(rects);
  567.             return;
  568.         }
  569.  
  570.         /* 5 */
  571.         if (aRect.x >= x && aRect.maxX() <= maxX()) {
  572.             if (aRect.y <= y && aRect.maxY() > maxY()) {
  573.                 rects.addElement(Rect.newRect(x, y, aRect.x - x, height));
  574.                 rects.addElement(Rect.newRect(aRect.maxX(), y,
  575.                                               maxX() - aRect.maxX(), height));
  576.             } else if (aRect.y <= y) {
  577.                 rects.addElement(Rect.newRect(x, y, aRect.x - x, height));
  578.                 rects.addElement(Rect.newRect(aRect.x, aRect.maxY(),
  579.                                               aRect.width,
  580.                                               maxY() - aRect.maxY()));
  581.                 rects.addElement(Rect.newRect(aRect.maxX(), y,
  582.                                               maxX() - aRect.maxX(), height));
  583.             } else {
  584.                 rects.addElement(Rect.newRect(x, y, aRect.x - x, height));
  585.                 rects.addElement(Rect.newRect(aRect.x, y, aRect.width,
  586.                                               aRect.y - y));
  587.                 rects.addElement(Rect.newRect(aRect.maxX(), y,
  588.                                               maxX() - aRect.maxX(), height));
  589.             }
  590.  
  591.             filterEmptyRects(rects);
  592.             return;
  593.         }
  594.  
  595.     }
  596.  
  597.  
  598.  
  599. /* archiving */
  600.  
  601.  
  602.     /** Describes the Rect class' coding information.
  603.       * @see Codable#describeClassInfo
  604.       */
  605.     public void describeClassInfo(ClassInfo info) {
  606.         info.addClass("netscape.application.Rect", 1);
  607.         info.addField(X_KEY, INT_TYPE);
  608.         info.addField(Y_KEY, INT_TYPE);
  609.         info.addField(WIDTH_KEY, INT_TYPE);
  610.         info.addField(HEIGHT_KEY, INT_TYPE);
  611.     }
  612.  
  613.     /** Encodes the Rect.
  614.       * @see Codable#encode
  615.       */
  616.     public void encode(Encoder encoder) throws CodingException {
  617.         encoder.encodeInt(X_KEY, x);
  618.         encoder.encodeInt(Y_KEY, y);
  619.         encoder.encodeInt(WIDTH_KEY, width);
  620.         encoder.encodeInt(HEIGHT_KEY, height);
  621.     }
  622.  
  623.     /** Decodes the Rect.
  624.       * @see Codable#decode
  625.       */
  626.     public void decode(Decoder decoder) throws CodingException {
  627.         x = decoder.decodeInt(X_KEY);
  628.         y = decoder.decodeInt(Y_KEY);
  629.         width = decoder.decodeInt(WIDTH_KEY);
  630.         height = decoder.decodeInt(HEIGHT_KEY);
  631.     }
  632.  
  633.     /** Finishes the Rect decoding.  This method does nothing.
  634.       * @see Codable#finishDecoding
  635.       */
  636.     public void finishDecoding() throws CodingException {
  637.     }
  638.  
  639.  
  640.  
  641.  
  642. /* rect cache */
  643.  
  644.  
  645.     /** Returns a Rect from the Rect cache with origin (<b>x</b>, <b>y</b>)
  646.       * and size (<b>width</b>, <b>height</b>).  Creates a new Rect if the
  647.       * cache is empty.
  648.       * @private
  649.       */
  650.     static Rect newRect(int x, int y, int width, int height) {
  651.         Rect    theRect;
  652.  
  653.         synchronized(_rectCache) {
  654.             if (!_cacheRects || _rectCache.isEmpty()) {
  655.                 return new Rect(x, y, width, height);
  656.             }
  657.  
  658.             theRect = (Rect)_rectCache.removeLastElement();
  659.         }
  660.         theRect.setBounds(x, y, width, height);
  661.  
  662.         return theRect;
  663.     }
  664.  
  665.     /** Returns a Rect from the Rect cache whose origin and size match
  666.       * <b>templateRect</b>.  Creates a new Rect if the cache is empty.
  667.       * @private
  668.       */
  669.     static Rect newRect(Rect templateRect) {
  670.         if (templateRect == null) {
  671.             return Rect.newRect(0, 0, 0, 0);
  672.         } else {
  673.             return Rect.newRect(templateRect.x, templateRect.y,
  674.                                 templateRect.width, templateRect.height);
  675.         }
  676.     }
  677.  
  678.     /** Returns a Rect from the Rect cache with origin (0, 0) and zero size.
  679.       * Equivalent to the code:
  680.       * <pre>
  681.       *     Rect.newRect(0, 0, 0, 0);
  682.       * </pre>
  683.       * Creates a new Rect if the cache is empty.
  684.       * @private
  685.       */
  686.     static Rect newRect() {
  687.         return Rect.newRect(0, 0, 0, 0);
  688.     }
  689.  
  690.  
  691.     /** Places aRect back in the Rect cache (if the cache is not full).
  692.       * @private
  693.       */
  694.     static void returnRect(Rect aRect) {
  695.         if (!_cacheRects) {
  696.             return;
  697.         }
  698.  
  699.         synchronized(_rectCache) {
  700.             if (_rectCache.count() < 50) {
  701.                 _rectCache.addElement(aRect);
  702.             }
  703.         }
  704.     }
  705.  
  706.     /** Places the Rects contained in <b>rects</b> back in the Rect cache
  707.       * (if the cache is not full) and empties the Vector.
  708.       * @private
  709.       */
  710.     static void returnRects(Vector rects) {
  711.         int     i;
  712.  
  713.         if (rects == null || !_cacheRects) {
  714.             return;
  715.         }
  716.  
  717.         i = rects.count();
  718.         while (i-- > 0) {
  719.             Rect.returnRect((Rect)rects.elementAt(i));
  720.         }
  721.  
  722.         rects.removeAllElements();
  723.     }
  724.  
  725.     /** Enables and disables Rect caching.  With setShouldCacheRects(false),
  726.       * Rect.newRect() methods create new Rects and Rect.returnRect() methods
  727.       * do nothing with the Rects they're given.  Disabling Rect caching can
  728.       * help you track down problems in your code of returning Rects to the
  729.       * cache while accidentally continuing to maintain references to them.
  730.       * @private
  731.       */
  732.     static void setShouldCacheRects(boolean flag) {
  733.         synchronized(_rectCache) {
  734.             _cacheRects = flag;
  735.             if (!_cacheRects) {
  736.                 _rectCache.removeAllElements();
  737.             }
  738.         }
  739.     }
  740. }
  741.